package com.afb

import grails.util.*
import java.io.*;
import java.util.*;

//import com.afb.EmailerService;

import org.biojava.bio.*;
import org.biojava.bio.seq.Sequence;
import org.biojava.bio.seq.SequenceIterator;
import org.biojava.bio.seq.db.*;
import org.biojava.bio.seq.io.*;
import org.biojava.bio.symbol.*;


import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


//import org.codehaus.groovy.grails.web.context.ServletContextHolder as SCH
//def servletContext = SCH.servletContext


class HHPredJobController {

    static allowedMethods = [save: "POST", update: "POST", delete: "POST"]

//    def fastaServiceService;
//    def fastaService

//    def hHPredService;
//
//    def hhPredService;
//    def hhpredService;

    def predService;

    
//    def hpredService;
    def emailerService;


    def teste = {
        render("done");
    }

    def index = {
        redirect(action: "list", params: params)
    }

    def list = {
        servletContext.texte = [1:"tralala",2:"obaoba"]

        params.max = Math.min(params.max ? params.int('max') : 10, 100)
//        [HHPredJobInstanceList: HHPredJob.list(params), HHPredJobInstanceTotal: HHPredJob.count()]
// TODO limitar maximo de processos a ser visto
        [HHPredJobInstanceList: HHPredJob.findAllByUser(session?.user), HHPredJobInstanceTotal: HHPredJob.count()]
//        [HHPredJobInstanceList: HHPredJob.findByUser(User.get(1)), HHPredJobInstanceTotal: HHPredJob.count()]
    }



    def createNew = {
        
        def HHPredJobInstance = new HHPredJob()

        HHPredJobInstance.properties = params
        return [HHPredJobInstance: HHPredJobInstance]
    }



    def create = {
        
        def HHPredJobInstance = new HHPredJob()
        
        HHPredJobInstance.properties = params
        return [HHPredJobInstance: HHPredJobInstance]
    }


    boolean validateProteins(String proteins) {

    try {
        BufferedInputStream is =
        new BufferedInputStream(new ByteArrayInputStream(proteins.getBytes("UTF-8")));

        //get the appropriate Alphabet
        //      Alphabet alpha = AlphabetManager.alphabetForName(args[1]);
        Alphabet alpha = AlphabetManager.alphabetForName("PROTEIN");

        //get a SequenceDB of all sequences in the file
        SequenceDB db = SeqIOTools.readFasta(is, alpha);
        
            
        SequenceIterator si = db.sequenceIterator();
        
        while (si.hasNext()) {
            Sequence seq = si.nextSequence();
            if ((seq.seqString()==null) || (seq.seqString().equals(""))) {
                println "not existing sequence..."
                return false

            }
        }
    }
    catch (BioException ex) {
      println "VOU ATIRAR UMA EXCEPCAO!!!!!!!"
      return false
      //not in fasta format or wrong alphabet
//      ex.printStackTrace();

    }catch (NoSuchElementException ex) {

      return false
      //no fasta sequences in the file
      ex.printStackTrace();

    }catch (FileNotFoundException ex) {

      return false
      //problem reading file
      ex.printStackTrace();

    }

    return true

    }


    def save = {

        println "Saving HHPredJob..."

        String parami=""
        String temp = ""
        params.each{
            parami += "$it<br/>"

        }
//        //render parami

        def HHPredJobInstance = new HHPredJob(params)

        println ""
        println "maxPairWiseSeqId :" + HHPredJobInstance.maxPairWiseSeqId
        println "diff             : " + HHPredJobInstance.diff
        println "cov              : " + HHPredJobInstance.cov
        println "qid              : " + HHPredJobInstance.qid
        println "qsc              : " + HHPredJobInstance.qsc

        println "corr             : " + HHPredJobInstance.corr
        println "realign          : " + HHPredJobInstance.realign
        println "ssm              : " + HHPredJobInstance.ssm
        println "globloc          : " + HHPredJobInstance.globloc
        println "ssw              : " + HHPredJobInstance.ssw
        println "alt              : " + HHPredJobInstance.alt
        println "description      : " + HHPredJobInstance.description
        println "name             : " + HHPredJobInstance.name
        println "mact             : " + HHPredJobInstance.mact

        println "zmax             : " + HHPredJobInstance.zmax
        println "qsc              : " + HHPredJobInstance.qsc
        println "e                : " + HHPredJobInstance.e
        println "proteinSequences : " + HHPredJobInstance.proteinSequences
        println "hmmDatabases     : " + HHPredJobInstance.hmmDatabases

        println "bmin             : " + HHPredJobInstance.bmin
        println "aliw             : " + HHPredJobInstance.aliw
        println "bmax             : " + HHPredJobInstance.bmax
        println "p                : " + HHPredJobInstance.p
        println "zmin             : " + HHPredJobInstance.zmin
        println "shift            : " + HHPredJobInstance.shift


//HHPredJobInstance.aliw = 0
//HHPredJobInstance.p = 0
//HHPredJobInstance.zmax = 0
//HHPredJobInstance.zmin = 0
//HHPredJobInstance.bmax = 0
//HHPredJobInstance.bmin = 0
//HHPredJobInstance.alt = 0
//HHPredJobInstance.ssm = 0
HHPredJobInstance.ssw = 0.11

//    int aliw
//    int p
//    int zmax
//    int zmin
//    int bmax
//    int bmin
//    int alt
//    int ssm



println ""
println ""
println ""

        
//        render parami




//    // [0,100] maximum pairwise sequence identity (%) (def=90) [0,100]
////    float id
//    String maxPairWiseSeqId
//
//    // filter most diverse set of sequences, keeping at least this many sequences in each block of >50 columns (def=100)
//    int diff
//
//    // [0,100] minimum coverage with query (%) (def=0)
////    float cov
//    String cov
//
//    // [0,100] minimum sequence identity with query (%) (def=0)
////    float qid
//    String qid
//
//    // [0,100] minimum score per column with query  (def=-20.0)
////    float qsc
//    String qsc










//        println "o zip é " + request.getFile("proteinSequencesZIP").inputStream.text

        String submitedFastaFile = request.getFile("proteinSequencesZIP").inputStream.text

        println "SubmitedFastaFile : "+ submitedFastaFile

        if (!submitedFastaFile.equals("")) {
            HHPredJobInstance.proteinSequences = submitedFastaFile
        }

        if (!validateProteins(HHPredJobInstance.proteinSequences)) {
//            render ("nao funca")
//            error.message = "${message(code: 'default.not.found.message', args: [message(code: 'HHPredJob.label', default: 'HHPredJob'), params.id])}"

//            HHPredJobInstance.errors.reject('invalid.fasta.submited',                           // Error code, see grails-app/i18n/message.properties
//                       ['password', 'class User'].toArray(),                            // Groovy ListArray cast to Object[]
//                       '[Property [{0}] of class [{1}] does not match confirmation]')   // Default mapping string


            HHPredJobInstance.errors.reject('invalid.fasta.submited')                           // Error code, see grails-app/i18n/message.properties

            render(view: "create", model: [HHPredJobInstance: HHPredJobInstance])
        } else {

        HHPredJobInstance.status = "processing"
//        HHPredJobInstance.status = "finished"
        println ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> vou gravar..."
        if (HHPredJobInstance.save(flush: true)) {
            println ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> gravei"
            flash.message = "${message(code: 'default.created.message', args: [message(code: 'HHPredJob.label', default: 'HHPredJob'), HHPredJobInstance.id])}"

//            fastaServiceService.addProcesses(HHPredJobInstance)
//            fastaService.addProcesses(HHPredJobInstance)



//            println "hHPredService : " + hHPredService
//            println "hhPredService : " + hhPredService
//            println "hhpredService : " + hhpredService
            println "predService : " + predService
            println "emailerService : " + emailerService


            predService.addProcesses(HHPredJobInstance)

            println "IAHOOOO : " +servletContext.queuedProcesses

            redirect(action: "show", id: HHPredJobInstance.id)
        }
        else {
            println ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> NAO gravei"
            render(view: "create", model: [HHPredJobInstance: HHPredJobInstance])
        }
        }

    }

    def show = {
        println "passei aki0"
        println "params.id : "  + params.id
        def HHPredJobInstance = HHPredJob.get(params.id)
        println "passei aki"

        if (!HHPredJobInstance) {
            flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'HHPredJob.label', default: 'HHPredJob'), params.id])}"
            redirect(action: "list")
        }
        else {

            println ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> números de processos : "+ Process.count()

//        findAllByEquipament(equipamentInstance)

        params.max = Math.min(params.max ? params.int('max') : 10, 100)
        [HHPredJobInstance: HHPredJobInstance, processInstanceList: Process.findAllByJob(HHPredJobInstance), processInstanceTotal: Process.count()]

//            [HHPredJobInstance: HHPredJobInstance]
        }
    }

    def edit = {
        def HHPredJobInstance = HHPredJob.get(params.id)
        if (!HHPredJobInstance) {
            flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'HHPredJob.label', default: 'HHPredJob'), params.id])}"
            redirect(action: "list")
        }
        else {
            return [HHPredJobInstance: HHPredJobInstance]
        }
    }

    def update = {
        def HHPredJobInstance = HHPredJob.get(params.id)
        if (HHPredJobInstance) {
            if (params.version) {
                def version = params.version.toLong()
                if (HHPredJobInstance.version > version) {
                    
                    HHPredJobInstance.errors.rejectValue("version", "default.optimistic.locking.failure", [message(code: 'HHPredJob.label', default: 'HHPredJob')] as Object[], "Another user has updated this HHPredJob while you were editing")
                    render(view: "edit", model: [HHPredJobInstance: HHPredJobInstance])
                    return
                }
            }
            HHPredJobInstance.properties = params
            if (!HHPredJobInstance.hasErrors() && HHPredJobInstance.save(flush: true)) {
                flash.message = "${message(code: 'default.updated.message', args: [message(code: 'HHPredJob.label', default: 'HHPredJob'), HHPredJobInstance.id])}"
                redirect(action: "show", id: HHPredJobInstance.id)
            }
            else {
                render(view: "edit", model: [HHPredJobInstance: HHPredJobInstance])
            }
        }
        else {
            flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'HHPredJob.label', default: 'HHPredJob'), params.id])}"
            redirect(action: "list")
        }
    }

    def delete = {
        def HHPredJobInstance = HHPredJob.get(params.id)
        if (HHPredJobInstance) {
            try {
                HHPredJobInstance.delete(flush: true)
                flash.message = "${message(code: 'default.deleted.message', args: [message(code: 'HHPredJob.label', default: 'HHPredJob'), params.id])}"
                redirect(action: "list")
            }
            catch (org.springframework.dao.DataIntegrityViolationException e) {
                flash.message = "${message(code: 'default.not.deleted.message', args: [message(code: 'HHPredJob.label', default: 'HHPredJob'), params.id])}"
                redirect(action: "show", id: params.id)
            }
        }
        else {
            flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'HHPredJob.label', default: 'HHPredJob'), params.id])}"
            redirect(action: "list")
        }
    }


    def run = {
        def HHPredJobInstance = HHPredJob.get(params.id)
        if (HHPredJobInstance) {
            try {

//                HHPredJobInstance.delete(flush: true)
                flash.message = "${message(code: 'default.deleted.message', args: [message(code: 'HHPredJob.label', default: 'HHPredJob'), params.id])}"
                println "aplicacao : " + servletContext.texte
//                hpredService.runJob(HHPredJobInstance, session.user.login);
                redirect(action: "list")
            }
            catch (org.springframework.dao.DataIntegrityViolationException e) {
                flash.message = "${message(code: 'default.not.deleted.message', args: [message(code: 'HHPredJob.label', default: 'HHPredJob'), params.id])}"
                redirect(action: "show", id: params.id)
            }
        }
        else {
            flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'HHPredJob.label', default: 'HHPredJob'), params.id])}"
            redirect(action: "list")
        }
    }






    def output = {
        def processInstance = Process.get(params.id)
        if (processInstance) {

            println " Output do process :"
            println processInstance.output

            return [processInstance: processInstance]

//            try {
//
////                HHPredJobInstance.delete(flush: true)
//                flash.message = "${message(code: 'default.deleted.message', args: [message(code: 'HHPredJob.label', default: 'HHPredJob'), params.id])}"
//                println "aplicacao : " + servletContext.texte
////                hpredService.runJob(HHPredJobInstance, session.user.login);
//                redirect(action: "list")
//            }
//            catch (org.springframework.dao.DataIntegrityViolationException e) {
//                flash.message = "${message(code: 'default.not.deleted.message', args: [message(code: 'HHPredJob.label', default: 'HHPredJob'), params.id])}"
//                redirect(action: "show", id: params.id)
//            }
//        }
//        else {
//            flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'HHPredJob.label', default: 'HHPredJob'), params.id])}"
//            redirect(action: "list")
        }
    }


    def input = {
        Process processInstance = Process.get(params.id)
        println " input do processssssss : fsdafad"
        if (processInstance) {

            println "ai esta a instancia : " + processInstance

            println " input do processssssss :"
            println processInstance.input
//            redirect(action: "show", id: params.id)
            return [processInstance: processInstance]


//            try {
//
////                HHPredJobInstance.delete(flush: true)
//                flash.message = "${message(code: 'default.deleted.message', args: [message(code: 'HHPredJob.label', default: 'HHPredJob'), params.id])}"
//                println "aplicacao : " + servletContext.texte
////                hpredService.runJob(HHPredJobInstance, session.user.login);
//                redirect(action: "list")
//            }
//            catch (org.springframework.dao.DataIntegrityViolationException e) {
//                flash.message = "${message(code: 'default.not.deleted.message', args: [message(code: 'HHPredJob.label', default: 'HHPredJob'), params.id])}"
//                redirect(action: "show", id: params.id)
//            }
//        }
//        else {
//            flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'HHPredJob.label', default: 'HHPredJob'), params.id])}"
//            redirect(action: "list")
        }
    }



    def process = {
        Process processInstance = Process.get(params.id)
        println " input do processssssss : fsdafad"
        if (processInstance) {

            println "ai esta a instancia : " + processInstance

            println " input do processssssss :"
            println processInstance.input
//            redirect(action: "show", id: params.id)
            params.jobId = processInstance.job.id
            println "JOBID : " + params.jobId
            return [processInstance: processInstance]


//            try {
//
////                HHPredJobInstance.delete(flush: true)
//                flash.message = "${message(code: 'default.deleted.message', args: [message(code: 'HHPredJob.label', default: 'HHPredJob'), params.id])}"
//                println "aplicacao : " + servletContext.texte
////                hpredService.runJob(HHPredJobInstance, session.user.login);
//                redirect(action: "list")
//            }
//            catch (org.springframework.dao.DataIntegrityViolationException e) {
//                flash.message = "${message(code: 'default.not.deleted.message', args: [message(code: 'HHPredJob.label', default: 'HHPredJob'), params.id])}"
//                redirect(action: "show", id: params.id)
//            }
//        }
//        else {
//            flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'HHPredJob.label', default: 'HHPredJob'), params.id])}"
//            redirect(action: "list")
        }
    }


    // Send an email
    def mensagem = {
        // Each "email" is a simple Map

        params.to = "cristiano_manuel@hotmail.com"
        params.subject = "teste grails"
        params.body = "bla bla bla"

        def email = [
            to: [ params.to ],        // "to" expects a List, NOT a single email address
            subject: params.subject,
            text: params.body         // "text" is the email body
        ]

        println "email : " + email;


        println "emailerService : "  + emailerService

        // sendEmails expects a List
        emailerService.sendEmails([email])
        render("done")
    }


    // Search Results
    def search = {

                def keyword = params.search.split(",")

                def KEYWORD = []

                keyword.collect(KEYWORD) {
                  it.trim()
                }

                println " keyword : " +KEYWORD

                HashMap<String,ArrayList> putativeMatchs = new HashMap<String,ArrayList>();

                // so pra debug .. qd apagar apagar todas as referencias dependentes..
                int contador = 0;

                HHPredJob jobe = HHPredJob.get(params.id)

                def listaDeProcessos = Process.findAllByJob(jobe)

              
                println "lista De Processos : " + listaDeProcessos
        
                listaDeProcessos.each {p ->

                println ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
                println "Vou analizar o processo "+ p.input

                String texto = p.output

//            String regul = ">[-.)( :a-zA-z0-9}{,']+"; // este funciona
//            Pattern pattern = Pattern.compile(regul, Pattern.CASE_INSENSITIVE);
//            String regul = ">([-.)( :a-zA-z0-9}{,'\\n])%+";

//                String regul = ">[-.)( :a-zA-z0-9}{,'\\s\\=]+"
                String regul = ">[-.)( :a-zA-z0-9}{,'\\s\\=/%]+" // sera que assim ja aceita a barra?
                Pattern pattern = Pattern.compile(regul, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE );

                Matcher matcher = pattern.matcher(texto);

                boolean found = false;

                    while (matcher.find()) {

                    println "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"

                    println "Vou analizar o match : " + matcher.group()

                //                    System.out.println("I found the text " + matcher.group() + " starting at index " + matcher.start() + " and ending at index " + matcher.end() + ".\n");
                        found = true;
                        for (int j = 0; j < KEYWORD.size(); j++) {

                    // Anywhere
//                            if (matcher.group().matches("(?i).*"+KEYWORD[j]+".*")) {  // este funciona
                            if (matcher.group().find("(?i).*"+KEYWORD[j]+".*")) {  // este funciona
                                println "Encontrei a keyword : " + KEYWORD[j]

//                            if (matcher.group().toLowerCase().indexOf(KEYWORD[j].toLowerCase())!=-1) {  // este funciona
//                            if (matcher.group().indexOf(KEYWORD[j]) != -1) {
    //                            putativeMatchs.add(filename);
                                ArrayList<String> listaDePutatives = putativeMatchs.get(p.name);
                                if (listaDePutatives==null) {
                                    listaDePutatives = new ArrayList<String>();
                                    putativeMatchs.put(p.name, listaDePutatives);
                                }
                                listaDePutatives.add(matcher.group());
                                contador++;
                            }
                        }
                    }
                    if (!found) {
                        System.out.println("No match found.\n");
                    }

                    System.out.println("Encontrei "+ contador +"");
                }

        System.out.println("___________________________________________________________________");


        def matchInstanceList = []
        def matchInstance = new Match()
        def teste = new Teste()
        teste.at1 = "atributo1"
        teste.at2 = "atributo2"

//        println "teste : " + teste;

        println "matchInstance : " + matchInstance;


        if (putativeMatchs.isEmpty()) {
            System.out.println("Nao encontrei nada...");
        } else {

//            Set<String> chaves  = putativeMatchs.keySet();

            Set<Entry<String, ArrayList>> matches = putativeMatchs.entrySet();

            // For both the keys and values of a map
            for (Iterator<Entry<String, ArrayList>> ite = matches.iterator(); ite.hasNext(); ) {
                Entry<String, ArrayList> entry = ite.next();
                String key = entry.getKey();
                ArrayList value = entry.getValue();

                System.out.println("________________________________________________________________________");
                System.out.println(">Chave : " + key);

                for (int f = 0;f<value.size();f++) {
//                    System.out.println("        " + value.get(f));



/* TODO */                matchInstance = new Match()
/* TODO */                matchInstance.job = Job.get(1)
/* TODO */                println "match : "+matchInstance
/* TODO */                println ""
/* TODO */                matchInstance.proc = Process.findByName(key)
/* TODO */                matchInstance.job = matchInstance.proc.job


//                            println "value.get(f) :"+value.get(f)
//                            println "value.get(f).indexOf('>') :"+value.get(f).indexOf('>')
//                            println "value.get(f).indexOf('Prob') :"+value.get(f).indexOf('Prob')


/* TODO */                matchInstance.hit = value.get(f).substring(value.get(f).indexOf('>'),value.get(f).indexOf('Prob'))
/* TODO */   //             matchInstance.hit = value.get(f).substring(value.get(f).indexOf('>'),value.get(f).indexOf('Probab'))


/* TODO */     //           matchInstanceList.add(matchInstance)


                        String input = value.get(f), extracted;

                        extracted = input.substring(input.indexOf('Probab=')+7,input.indexOf('E-value')-1);
//                        println " prob " + extracted
                        matchInstance.prob = extracted

                        extracted = input.substring(input.indexOf('E-value=')+8,input.indexOf('Score')-1);
//                        println " evalue " + extracted
                        matchInstance.eValue = extracted

                        // sera que estou a usar a ultima versao do hhsearch? Tinha isto para outro output..
//                        extracted = input.substring(input.indexOf('Score=')+6,input.indexOf('Aligned_columns')-1);
                        extracted = input.substring(input.indexOf('Score=')+6,input.indexOf('Aligned_cols')-1);
//                        println " Score " + extracted
                        matchInstance.score = extracted

                        // sera que estou a usar a ultima versao do hhsearch? Tinha isto para outro output..
//                        extracted = input.substring(input.indexOf('Aligned_columns=')+16,input.indexOf('Identities')-1);
                        extracted = input.substring(input.indexOf('Aligned_cols=')+13,input.indexOf('Identities')-1);
//                        println " ssCols " + extracted
                        matchInstance.ssCols = extracted

                        // sera que estou a usar a ultima versao do hhsearch? Tinha isto para outro output..
//                        extracted = input.substring(input.indexOf('Aligned_columns=')+16,input.indexOf('Identities')-1);

//                        println "input : "+input
//                        println "input.indexOf('Identities=') : "+input.indexOf('Identities=')
//                        println "input.indexOf('Similarity=') : "+input.indexOf('Similarity=')
                        extracted = input.substring(input.indexOf('Identities=')+11,input.indexOf('Similarity')-1);
//                        println " Identities " + extracted
                        matchInstance.identities = extracted


                        extracted = input.substring(input.indexOf('Similarity=')+11,input.indexOf('Sum_probs')-1);
//                        println " similarity " + extracted
                        matchInstance.similarity = extracted

                        int indexSumProbs = input.indexOf('Sum_probs=')
                        extracted = input.substring(indexSumProbs+10,input.indexOf('\n',indexSumProbs));
//                        println " sum_probs " + extracted
                        matchInstance.sumProbs = extracted


                        matchInstanceList.add(matchInstance)
                }

            }
        }

        println "_________________________________________________________________________________________________"


        println "Número de matches  :   " + matchInstanceList.size()

        [matchInstanceList: matchInstanceList, matchInstanceTotal: matchInstanceList.size(),jobId: jobe.id, jobName: jobe.name, keywords: params.search]

    }

// controller action
    def time = {
        println "vou executar time..."
       render "eheh ${new Date()}"
    }

    def retry = {
        Process processInstance = Process.get(params.id)
        
//        fastaServiceService.cleanPossibleCreatedFiles(processInstance)
//        fastaService.cleanPossibleCreatedFiles(processInstance)
        predService.addProcesses(HHPredJobInstance)

        processInstance.status = "queued"
        servletContext.isListOfProcessesAltered = true;

        redirect(action: "process", id: params.id)
//        return [processInstance: processInstance]


    }








//def save = {
//                params.shouted = new Date()
////                def shout = new Shout(params)
////                shout.save()
//                render "Success!"
//        }
//
//        // Return the last 30 shouts
//        def fetch = {
//                def shouts = Shout.list(max: 30, sort: "shouted", order: "desc")
//                render (contentType: "text/xml") {
//                        shouts.reverseEach { shout ->
//                                p {
//                                        b("(" + shout.shouted.dateTimeString + ") " + shout.shouter + ": ")
//                                        span(shout.shout)
//                                }
//                        }
//                }
//
//        render "fetch"
//
//        }


}
